from celery import shared_task
from django.db.models import Avg, Max, Min, Count, Sum
from django.db.models import F, Q
from datetime import datetime, date, timedelta
from mysqldb.models import *

import time
import logging

logger = logging.getLogger(__name__)


@shared_task
def TasksReportTermLimit(sd, ed, t, pid):
    """获取所有数据"""
    # logger.info(f"{type(sd)},{sd}; {type(ed)},{ed}")

    def limit_date(d, st):
        """格式化日期"""
        # logger.info(f"TasksReportTermLimit {type(d)}")
        if st == "d":
            return d - timedelta(days=1)
        elif st == "w":
            return d - timedelta(days=7)
        elif st == "m":
            ty, tm, td = d.year, d.month - 1, d.day
            by = ty if tm > 0 else ty - 1
            bm = tm if tm > 0 else 12
            return date(by, bm, td)
        else:
            return {"rescode": 266, "resmsg": f"计算日期出错 {d} {t}"}

    def staff_data(sid):
        try:
            r = AllinpayStaffinterList.objects.get(id=sid)
        except BaseException as err:
            return ""
        else:
            return r.basename

    def callme_data(cid):
        try:
            r = AllinpayCallmeList.objects.get(id=cid)
            name = staff_data(r.target)
        except BaseException as err:
            return ""
        else:
            return name

    def do_select_money(s, e, p, g):
        """统计订单金额"""
        money = 0
        x = FsygShopreqsnList.objects.filter(
            wb_id=p,
            machine_no__in=g,
            message_type="order",
            order_status="2",
            create_time__range=(s, e),
        ).values_list("amount", flat=True)
        for i in list(x):
            money += int(float(i) * 100)
        return money

    def do_select_count(s, e, p, g):
        """查询订单数量"""
        x = FsygShopreqsnList.objects.filter(
            wb_id=p,
            machine_no__in=g,
            message_type="order",
            order_status="2",
            create_time__range=(s, e),
        ).count()
        return x

    def do_select_limit(s, e, p, g):
        """查询商品数量"""
        money = 0
        x = FsygShopreqsnList.objects.filter(
            wb_id=p,
            machine_no__in=g,
            message_type="order",
            order_status="2",
            create_time__range=(s, e),
        ).values_list("reqsn", flat=True)
        y = FsygShopintoList.objects.filter(order__in=list(x)).values_list(
            "count", flat=True
        )
        for i in list(y):
            money += int(i)
        return money

    def do_select_member(s, e, p, g):
        """统计会员订单金额"""
        money = 0
        x = FsygShopreqsnList.objects.filter(
            wb_id=p,
            maid__in=g,
            message_type="order",
            order_status="2",
            create_time__range=(s, e),
        ).values_list("amount", flat=True)
        for i in list(x):
            money += int(float(i) * 100)
        return money

    def do_select_callme(s, e, p, g):
        """统计配送订单金额"""
        money = 0
        # 查询订单列表
        r = AllinpayCallmeList.objects.filter(
            pid=p, target__in=g, current__range=(s, e)
        ).values_list("bem", flat=True)
        x = FsygShopreqsnList.objects.filter(
            message_type="order",
            order_status="2",
            reqsn__in=list(r),
        ).values_list("amount", flat=True)
        for i in list(x):
            money += int(float(i) * 100)
        return money

    def do_select_chart_shop(s, e, p, g):
        """统计排行榜商品"""
        r = FsygShopreqsnList.objects.filter(
            wb_id=p,
            message_type="order",
            order_status="2",
            create_time__range=(s, e),
        ).values_list("reqsn", flat=True)

        if not list(r):
            return []
        x = list(
            FsygShopintoList.objects.filter(order__in=list(r))
            .values("product_name")
            .annotate(tongji=Sum("count"))
        )
        if not x:
            return []

        x.sort(key=lambda c: c["tongji"], reverse=True)
        if len(x) > g:
            return x[:g]
        else:
            return x

    def do_select_chart_staff(s, e, p, g):
        """统计排行榜个人"""
        r = FsygShopreqsnList.objects.filter(
            wb_id=p,
            message_type="order",
            order_status="2",
            create_time__range=(s, e),
        ).values("amount", "delivery")
        if not list(r):
            return []
        d = []
        for i in list(r):
            name = callme_data(i["delivery"])
            if not name:
                continue
            d.append(
                {
                    "value": int(float(i["amount"]) * 100),
                    "name": name,
                }
            )
        money = []
        u = list(set([n["name"] for n in d]))
        for x in u:
            m = 0
            for y in d:
                if y["name"] == x:
                    m += y["value"]
            money.append({"name": x, "value": m})

        money.sort(key=lambda c: c["value"], reverse=True)
        if len(money) > g:
            return money[:g]
        else:
            return money

    # 查询当前数据
    # if type(sd) == "str":
    sd, ed = datetime.strptime(sd, "%Y-%m-%dT%H:%M:%S"), datetime.strptime(
        ed, "%Y-%m-%dT%H:%M:%S"
    )

    # if date.today() <= sd.date:
    #     return {"rescode": 204, "resmsg": "日期异常"}
    # logger.info(f"{sd.date}; {ed.date}; {datetime.today().date}")

    # 1.查询场所数据
    try:
        place = AllinpayPlaceList.objects.get(id=pid)
    except BaseException as err:
        return {"rescode": 266, "resmsg": "查询场所失败"}
    if not place.barcode:
        return {"rescode": 266, "resmsg": "场所未绑定 凡商编码"}
    # 2. 查询会员等级类型
    viplev = (
        FsygMemberList.objects.filter(wb_id=place.barcode)
        .exclude(level__isnull=True)
        .values_list("level", flat=True)
        .distinct()
    )
    # 3. 查询团队和成员
    teams = AllinpayStaffteamList.objects.filter(pid=pid).values("name", "staffs")
    # logger.info(f"{type(teams['staffs'])},{teams['staffs']}; ")
    # 4. 查询个人激励
    staff = GIncentivesConf.objects.filter(
        pid=pid, tid__isnull=True, sid__isnull=False
    ).values_list("sid", flat=True)
    # 2.查询场所区域终端
    data = []
    for i in list(
        FsygPchardList.objects.filter(pid=pid)
        .values_list("group", flat=True)
        .distinct()
    ):
        # 终端列表
        r = FsygPchardList.objects.filter(pid=pid, group=i).values_list(
            "name", flat=True
        )
        sess = {}
        sess["name"] = i
        # 订单金额
        sess["now_money"] = do_select_money(sd, ed, place.barcode, r)
        sess["last_money"] = do_select_money(
            limit_date(sd, t), limit_date(ed, t), place.barcode, r
        )
        # 订单数量
        sess["now_count"] = do_select_count(sd, ed, place.barcode, r)
        sess["last_count"] = do_select_count(
            limit_date(sd, t), limit_date(ed, t), place.barcode, r
        )
        # 商品数量
        sess["now_limit"] = do_select_limit(sd, ed, place.barcode, r)
        sess["last_limit"] = do_select_limit(
            limit_date(sd, t), limit_date(ed, t), place.barcode, r
        )
        # 单品数量
        sess["now_goods"] = 0
        sess["last_goods"] = 0
        # 组合数量
        sess["now_combo"] = 0
        sess["last_combo"] = 0
        # 会员统计
        member = []
        for j in list(viplev):
            # 会员列表
            s = FsygMemberList.objects.filter(wb_id=place.barcode, level=j).values_list(
                "codeid", flat=True
            )
            maijia = {}
            maijia["name"] = j
            maijia["now_money"] = do_select_member(sd, ed, place.barcode, s)
            maijia["last_money"] = do_select_member(
                limit_date(sd, t), limit_date(ed, t), place.barcode, s
            )
            member.append(maijia)
        sess["member"] = member
        # 统计团队
        team = []
        for k in teams:
            # 团队列表
            s = eval(k["staffs"])
            tuandui = {}
            tuandui["name"] = k["name"]
            tuandui["now_money"] = do_select_callme(sd, ed, place.barcode, s)
            tuandui["last_money"] = do_select_callme(
                limit_date(sd, t), limit_date(ed, t), place.barcode, s
            )
            team.append(tuandui)
        sess["teamer"] = team
        # 统计个人
        staffs = []
        for l in list(staff):
            geren = {}
            geren["name"] = staff_data(l)
            geren["now_money"] = do_select_callme(sd, ed, place.barcode, [l])
            geren["last_money"] = do_select_callme(
                limit_date(sd, t), limit_date(ed, t), place.barcode, [l]
            )
            staffs.append(geren)
        sess["staffer"] = staffs
        data.append(sess)
    chart_shaop = do_select_chart_shop(sd, ed, place.barcode, 20)
    chart_staff = do_select_chart_staff(sd, ed, place.barcode, 20)
    return {
        "rescode": 200,
        "resmsg": {
            "name": "同步数据",
            "data": data,
            "shop": chart_shaop,
            "staff": chart_staff,
        },
    }


@shared_task
def WorkListCountTask(**kwargs):
    """作业项任务统计"""

    def has_Place_Name(pid):
        """查询场所名"""
        try:
            r = AllinpayPlaceList.objects.get(id=pid)
        except BaseException as err:
            return ""
        else:
            return r.basename

    def has_Staff_Name(sid):
        """查询员工名称"""
        try:
            r = AllinpayStaffList.objects.get(id=sid)
        except BaseException as err:
            return ""
        else:
            return r.basename

    # logger.warn(f"WorkListCountTask {kwargs}")
    # 初始化变量
    timelen, asum, x = time.time(), 0, None
    # 分组查询
    q = AllinpayPlaceworkitemList.objects.filter(
        currentdate__gte=kwargs["star"],
        currentdate__lte=kwargs["stop"],
        pid__in=kwargs["pid"],
    )

    if kwargs.get("rptype") == 1:
        """报表维度 工作项标题"""
        x = list(q.values("title").annotate(c=Count("id"), pid=F("pid")).order_by("-c"))
        for i in range(len(x)):
            wids = list(q.filter(title=x[i]["title"]).values_list("id", flat=True))
            x[i]["submit"] = AllinpayPlaceworkitemSubmit.objects.filter(
                wid__in=wids
            ).count()
            x[i]["check"] = list(
                AllinpayPlaceworkitemCheck.objects.filter(wid__in=wids)
                .values("raward")
                .annotate(c=Count("id"))
            )
            x[i]["inter"] = AllinpayPlaceinterLog.objects.filter(
                reqsn__in=wids
            ).aggregate(Sum("inter"))
            wsub = list(
                AllinpayPlaceworkitemSubmit.objects.filter(wid__in=wids).values_list(
                    "id", flat=True
                )
            )
            x[i]["unc"] = x[i]["c"] - len(wsub)
            x[i]["name"] = has_Place_Name(x[i]["pid"])
            for j in range(len(x[i]["check"])):
                try:
                    n = AllinpayRawardList.objects.get(
                        id=int(x[i]["check"][j]["raward"])
                    )
                    m = AllinpayIntegralList.objects.get(id=n.intetype)
                except BaseException as err:
                    x[i]["check"][j]["name"] = ""
                    x[i]["check"][j]["parent"] = ""
                else:
                    x[i]["check"][j]["name"] = n.name
                    x[i]["check"][j]["parent"] = m.name
        asum = q.count()

    if kwargs.get("rptype") == 2:
        """报表维度 工作项执行人"""
        x = list(
            q.values("onstaff").annotate(c=Count("id"), pid=F("pid")).order_by("-c")
        )
        for i in range(len(x)):
            wids = list(q.filter(onstaff=x[i]["onstaff"]).values_list("id", flat=True))
            x[i]["submit"] = AllinpayPlaceworkitemSubmit.objects.filter(
                wid__in=wids
            ).count()
            x[i]["check"] = list(
                AllinpayPlaceworkitemCheck.objects.filter(wid__in=wids)
                .values("raward")
                .annotate(c=Count("id"))
            )
            x[i]["inter"] = AllinpayPlaceinterLog.objects.filter(
                reqsn__in=wids
            ).aggregate(Sum("inter"))
            wsub = list(
                AllinpayPlaceworkitemSubmit.objects.filter(wid__in=wids).values_list(
                    "id", flat=True
                )
            )
            x[i]["unc"] = x[i]["c"] - len(wsub)
            x[i]["staff"] = has_Staff_Name(x[i]["onstaff"])
            x[i]["name"] = has_Place_Name(x[i]["pid"])
            for j in range(len(x[i]["check"])):
                try:
                    n = AllinpayRawardList.objects.get(
                        id=int(x[i]["check"][j]["raward"])
                    )
                    m = AllinpayIntegralList.objects.get(id=n.intetype)
                except BaseException as err:
                    x[i]["check"][j]["name"] = ""
                    x[i]["check"][j]["parent"] = ""
                else:
                    x[i]["check"][j]["name"] = n.name
                    x[i]["check"][j]["parent"] = m.name
        asum = q.count()
    res = {
        "rescode": 200,
        "resmsg": x,
        # "placeName": pname,
        "sum": asum,
        "timer": time.time() - timelen,
    }
    # logger.warn(f"WorkListCountTask {res}")
    return res


@shared_task
def InterListCountTask(**kwargs):
    """作业项积分统计"""

    def has_Place_Name(pid):
        """查询场所名"""
        try:
            r = AllinpayPlaceList.objects.get(id=pid)
        except BaseException as err:
            return ""
        else:
            return r.basename

    def has_Staff_Name(sid):
        """查询员工名称"""
        try:
            r = AllinpayStaffList.objects.get(id=sid)
        except BaseException as err:
            return ""
        else:
            return r.basename

    # logger.warn(f"InterListCountTask {kwargs}")
    # 初始化变量
    timelen, x = time.time(), None
    # 分组查询
    q = AllinpayPlaceworkitemList.objects.filter(
        currentdate__gte=kwargs["star"],
        currentdate__lte=kwargs["stop"],
        pid__in=kwargs["pid"],
    )
    if kwargs.get("rptype") == 1:
        """报表维度 场所"""
        x = list(q.values("pid").annotate(c=Count("id")).order_by("-c"))
        for i in range(len(x)):
            wids = list(q.filter(pid=x[i]["pid"]).values_list("id", flat=True))
            x[i]["submit"] = AllinpayPlaceworkitemSubmit.objects.filter(
                wid__in=wids
            ).count()
            x[i]["check"] = list(
                AllinpayPlaceworkitemCheck.objects.filter(wid__in=wids)
                .values("raward")
                .annotate(c=Count("id"))
            )
            x[i]["inter"] = AllinpayPlaceinterLog.objects.filter(
                reqsn__in=wids
            ).aggregate(Sum("inter"))
            wsub = list(
                AllinpayPlaceworkitemSubmit.objects.filter(wid__in=wids).values_list(
                    "id", flat=True
                )
            )
            x[i]["unc"] = x[i]["c"] - len(wsub)
            x[i]["name"] = has_Place_Name(x[i]["pid"])
            for j in range(len(x[i]["check"])):
                try:
                    n = AllinpayRawardList.objects.get(
                        id=int(x[i]["check"][j]["raward"])
                    )
                    m = AllinpayIntegralList.objects.get(id=n.intetype)
                except BaseException as err:
                    x[i]["check"][j]["name"] = ""
                    x[i]["check"][j]["parent"] = ""
                else:
                    x[i]["check"][j]["name"] = n.name
                    x[i]["check"][j]["parent"] = m.name
    if kwargs.get("rptype") == 2:
        """报表维度 员工"""
        x = list(q.values("onstaff").annotate(c=Count("id")).order_by("-c"))
        for i in range(len(x)):
            wids = list(q.filter(onstaff=x[i]["onstaff"]).values_list("id", flat=True))
            x[i]["submit"] = AllinpayPlaceworkitemSubmit.objects.filter(
                wid__in=wids
            ).count()
            x[i]["check"] = list(
                AllinpayPlaceworkitemCheck.objects.filter(wid__in=wids)
                .values("raward")
                .annotate(c=Count("id"))
            )
            x[i]["inter"] = AllinpayPlaceinterLog.objects.filter(
                reqsn__in=wids
            ).aggregate(Sum("inter"))
            wsub = list(
                AllinpayPlaceworkitemSubmit.objects.filter(wid__in=wids).values_list(
                    "id", flat=True
                )
            )
            x[i]["unc"] = x[i]["c"] - len(wsub)
            x[i]["name"] = has_Staff_Name(x[i]["onstaff"])
            for j in range(len(x[i]["check"])):
                try:
                    n = AllinpayRawardList.objects.get(
                        id=int(x[i]["check"][j]["raward"])
                    )
                    m = AllinpayIntegralList.objects.get(id=n.intetype)
                except BaseException as err:
                    x[i]["check"][j]["name"] = ""
                    x[i]["check"][j]["parent"] = ""
                else:
                    x[i]["check"][j]["name"] = n.name
                    x[i]["check"][j]["parent"] = m.name

    # logger.warn(f"InterListCountTask {x}")
    return {"rescode": 200, "resmsg": x, "timer": time.time() - timelen}
